package com.clover.zookeeper;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;

/**
 * zookeeper分布式锁
 * Created by sanyecao on 2017/10/16.
 */
@Component
public class ZookeeperLockHelper {
    private static final Logger logger = LoggerFactory.getLogger(ZookeeperLockHelper.class);

    private CuratorFramework client = null;

    private int RETRIES_INTERVAL = 100;//重试间隔时间（单位：毫秒）

    private int MAX_RETRIES_COUNT = 3;//最大重试次数

    private String ZOOKEEPER_ADDRESS = "10.0.23.88:2181";//zookeeper 地址

    private long WAIT_TIME = 0;//超时等待时间



    /**
     * 初始化（类被加载时执行）
     */
    @PostConstruct
    private void init(){
        logger.info("==============初始化zookeeper客户端开始==============");
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(RETRIES_INTERVAL, MAX_RETRIES_COUNT);//连接策略
        client = CuratorFrameworkFactory.newClient(ZOOKEEPER_ADDRESS, retryPolicy);
        client.start();
        logger.info("==============初始化zookeeper客户端结束==============");
    }


    /**
     * 创建zookeeper节点
     * @param node
     * @return
     */
    public InterProcessMutex createPath(String node){
        try{
            long startTime = System.currentTimeMillis();
            InterProcessMutex lock = new InterProcessMutex(client,node);
            logger.info("创建节点耗时:{}",System.currentTimeMillis() - startTime);
            return lock;
        }catch (Exception e){
            logger.error("创建zookeeper锁异常",e);
            return null;
        }
    }

    /**
     * 获取锁
     * @param lock
     * @return
     */
    public Boolean acquire(InterProcessMutex lock){
        try{
            long startTime = System.currentTimeMillis();
            Boolean result = lock.acquire(WAIT_TIME, TimeUnit.MILLISECONDS);
            logger.info("获取zookeeper锁结果:{},耗时:{}",result,System.currentTimeMillis() - startTime);
            return result;
        }catch (Exception e){
           logger.error("获取zookeeper锁异常",e);
        }
        return Boolean.FALSE;
    }


    /**
     * 释放锁
     */
    public void release(InterProcessMutex lock,String node){
        try{
            if(lock != null) {
                //释放锁
                lock.release();
                logger.info("释放zookeeper锁成功！");
                //删除节点
                if(client != null && client.checkExists().forPath(node) != null){
                    client.delete().forPath(node);
                    logger.info("删除zookeeper锁节点成功！");
                }
            }
        }catch (Exception e){
            logger.error("释放zookeeper锁异常",e);
        }
    }

}
